home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume18 / elm2.2 / part24 < prev    next >
Encoding:
Internet Message Format  |  1989-04-12  |  40.9 KB

  1. Subject:  v18i103:  Elm mail system, release 2.2, Part24/22
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: dsinc!syd@uunet.UU.NET (Syd Weinstein)
  7. Posting-number: Volume 18, Issue 103
  8. Archive-name: elm2.2/part24
  9.  
  10. #!/bin/sh
  11. # this is part 24 of a multipart archive
  12. # do not concatenate these parts, unpack them in order with /bin/sh
  13. # file utils/newalias.c continued
  14. #
  15. CurArch=24
  16. if test ! -r s2_seq_.tmp
  17. then echo "Please unpack part 1 first!"
  18.      exit 1; fi
  19. ( read Scheck
  20.   if test "$Scheck" != $CurArch
  21.   then echo "Please unpack part $Scheck next!"
  22.        exit 1;
  23.   else exit 0; fi
  24. ) < s2_seq_.tmp || exit 1
  25. echo "x - Continuing file utils/newalias.c"
  26. sed 's/^X//' << 'SHAR_EOF' >> utils/newalias.c
  27. X      exit(1);
  28. X    }
  29. X
  30. X    loc = hash_it(word, size);
  31. X
  32. X    while (table[loc].name[0] != '\0' && strcmp(table[loc].name, word) != 0)
  33. X      loc = (loc + 1) % size; 
  34. X
  35. X    if (table[loc].name[0] == '\0') {
  36. X      strcpy(table[loc].name, word);
  37. X      table[loc].byte = offset;
  38. X    }
  39. X    else 
  40. X      printf("** Duplicate alias '%s' in file.  Multiples ignored.\n",
  41. X             word);
  42. X}
  43. X
  44. Xint
  45. Xhash_it(string, table_size)
  46. Xchar *string;
  47. X{
  48. X    /** compute the hash function of the string, returning
  49. X        it (mod table_size) **/
  50. X
  51. X    register int i, sum = 0;
  52. X    
  53. X    for (i=0; string[i] != '\0'; i++)
  54. X      sum += (int) string[i];
  55. X
  56. X    return(sum % table_size);
  57. X}
  58. X
  59. Xinit_table(table, size)
  60. Xstruct alias_rec table[];
  61. Xint size;
  62. X{
  63. X    /** initialize hash table! **/
  64. X
  65. X    register int i;
  66. X
  67. X    for (i=0; i < size; i++)
  68. X      table[i].name[0] = '\0';
  69. X}
  70. X
  71. Xread_in_system(table, size)
  72. Xstruct alias_rec table[];
  73. Xint size;
  74. X{
  75. X    /** read in the system hash table...to check for group aliases
  76. X        from the user alias file (to ensure that there are no names
  77. X        in the user group files that are not purely contained within
  78. X        either alias table) **/
  79. X    
  80. X    int  fd;
  81. X    char fname[SLEN];
  82. X
  83. X    sprintf(fname, "%s/%s", mailhome, ALIAS_HASH);
  84. X
  85. X    if ((fd = open(fname, O_RDONLY)) == -1)
  86. X      return;    /* no sweat: flag 'hash_table_loaded' not set! */
  87. X
  88. X    (void) read(fd, table, size);
  89. X    close(fd);
  90. X    hash_table_loaded++;
  91. X}
  92. X    
  93. Xcheck_group(names, groupname)
  94. Xchar *names, *groupname;
  95. X{
  96. X    /** one by one make sure each name in the group is defined
  97. X        in either the system alias file or the user alias file.
  98. X        This search is linearly dependent, so all group aliases
  99. X        in the source file should appear LAST, after all the user
  100. X        aliases! **/
  101. X
  102. X    char *word, *bufptr, buffer[LONG_STRING];
  103. X
  104. X    strcpy(buffer, names);
  105. X    bufptr = (char *) buffer;
  106. X
  107. X    while ((word = (char *) strtok(bufptr,", ")) != NULL) {
  108. X      if (! can_find(word)) 
  109. X        if (! valid_name(word)) {
  110. X          error++;
  111. X          printf("** Alias %s in group %s is bad!\n", word, groupname);
  112. X        }
  113. X      bufptr = NULL;
  114. X    }
  115. X}
  116. X
  117. Xint
  118. Xcan_find(name)
  119. Xchar *name;
  120. X{    
  121. X    /** find name in either hash table...use 'is_system' variable to
  122. X        determine if we should look in both or just system....    **/
  123. X
  124. X    register int loc;
  125. X    
  126. X    if (strlen(name) > 20) {
  127. X      error++;
  128. X      printf("** Bad alias name: %s.  Too long.\n", name);
  129. X      return(1);    /* fake out: don't want 2 error messages! */
  130. X    }
  131. X
  132. X    /** system alias table... **/
  133. X    if (hash_table_loaded || is_system) {
  134. X      loc = hash_it(name, MAX_SALIASES);
  135. X
  136. X      while (strcmp(name, shash_table[loc].name) != 0 && 
  137. X                 shash_table[loc].name[0] != '\0')
  138. X        loc = (loc + 1) % MAX_SALIASES; 
  139. X  
  140. X      if (strcmp(name, shash_table[loc].name) == 0)
  141. X        return(1);    /* found it! */
  142. X    }
  143. X
  144. X    if (! is_system) {    /* okay! Let's check the user alias file! */
  145. X      loc = hash_it(name, MAX_UALIASES);
  146. X
  147. X      while (strcmp(name, uhash_table[loc].name) != 0 && 
  148. X                 uhash_table[loc].name[0] != '\0')
  149. X        loc = (loc + 1) % MAX_UALIASES; 
  150. X
  151. X      if (strcmp(name, uhash_table[loc].name) == 0)
  152. X        return(1);    /* found it! */
  153. X    }
  154. X
  155. X    return(0);
  156. X}
  157. X
  158. Xextract_comment(comment, buffer, first, last)
  159. Xchar *comment, *buffer;
  160. Xint first, last;
  161. X{
  162. X    /** Buffer contains a comment, located between the first and last
  163. X        values.  Copy that into 'comment', but remove leading and
  164. X        trailing white space.  Note also that it doesn't copy past
  165. X        a comma, so `unpublishable' comments can be of the form;
  166. X        dave: Dave Taylor, HP Labs : taylor@hplabs
  167. X        and the output will be "taylor@hplabs (Dave Taylor)".
  168. X    **/
  169. X
  170. X    register int loc = 0; 
  171. X
  172. X    /** first off, skip the LEADING white space... **/
  173. X
  174. X    while (whitespace(buffer[first])) first++;
  175. X    
  176. X    /** now let's backup the 'last' value until we hit a non-whitespace **/
  177. X
  178. X    last -= 2;    /* starts at ch AFTER equals.. */
  179. X    while (whitespace(buffer[last])) last--;
  180. X
  181. X    /** now a final check to make sure we're still talking about a 
  182. X        reasonable string (rather than a "joe :: joe@dec" type string) **/
  183. X
  184. X    if (first < last) {
  185. X      /* one more check - let's find the comma, if present... */
  186. X      for (loc=first; loc < last; loc++)
  187. X        if (buffer[loc] == ',') {
  188. X          last = loc-1;
  189. X          break;
  190. X      }
  191. X      loc = 0;
  192. X      while (first <= last)
  193. X        comment[loc++] = buffer[first++];
  194. X      comment[loc] = '\0';
  195. X    }
  196. X}
  197. X
  198. Xupdate_alias_file_locations()
  199. X{
  200. X    /** a short-term routine to ensure that the data files are
  201. X        moved into the correct directory... **/
  202. X
  203. X    char source[SLEN], dest[SLEN];
  204. X
  205. X    /** first let's create the directory if it ain't there... **/
  206. X
  207. X    sprintf(source, "%s/.elm", home);
  208. X
  209. X    /** Some systems don't have a mkdir call - how inconvienient! **/
  210. X#ifdef MKDIR
  211. X    (void) mkdir(source, 0700);
  212. X#else
  213. X    system("mkdir $HOME/.elm");
  214. X    system("chmod 700 $HOME/.elm");
  215. X#endif /* MKDIR */
  216. X
  217. X    /** now *link* the files... **/
  218. X
  219. X    sprintf(source, "%s/.alias_text", home);
  220. X    sprintf(dest,   "%s/%s",          home, ALIAS_TEXT);
  221. X    link(source, dest);
  222. X
  223. X    sprintf(source, "%s/.alias_hash", home);
  224. X    sprintf(dest,   "%s/%s",          home, ALIAS_HASH);
  225. X    link(source, dest);
  226. X
  227. X    sprintf(source, "%s/.alias_data", home);
  228. X    sprintf(dest,   "%s/%s",          home, ALIAS_DATA);
  229. X    link(source, dest);
  230. X
  231. X    printf("\n*** Moved all data files into %s/.elm directory ***\n\n",
  232. X        home);
  233. X}
  234. SHAR_EOF
  235. echo "File utils/newalias.c is complete"
  236. chmod 0444 utils/newalias.c || echo "restore of utils/newalias.c fails"
  237. echo "x - extracting utils/newmail.c (Text)"
  238. sed 's/^X//' << 'SHAR_EOF' > utils/newmail.c &&
  239. X
  240. Xstatic char rcsid[] = "@(#)$Id: newmail.c,v 2.16 89/03/25 21:47:55 syd Exp $";
  241. X
  242. X/*******************************************************************************
  243. X *  The Elm Mail System  -  $Revision: 2.16 $   $State: Exp $
  244. X *
  245. X *             Copyright (c) 1986, 1987 Dave Taylor
  246. X *             Copyright (c) 1988, 1989 USENET Community Trust
  247. X *******************************************************************************
  248. X * Bug reports, patches, comments, suggestions should be sent to:
  249. X *
  250. X *    Syd Weinstein, Elm Coordinator
  251. X *    elm@dsinc.UUCP            dsinc!elm
  252. X *
  253. X *******************************************************************************
  254. X * $Log:    newmail.c,v $
  255. X * Revision 2.16  89/03/25  21:47:55  syd
  256. X * Initial 2.2 Release checkin
  257. X * 
  258. X *
  259. X ******************************************************************************/
  260. X
  261. X/** This is actually two programs folded into one - 'newmail()' and
  262. X    'wnewmail()'.  They perform essentially the same function, to
  263. X    monitor the mail arriving in a set of/a mailbox or folder, but
  264. X    newmail is designed to run in background on a terminal, and
  265. X    wnewmail is designed to have a window of its own to run in.
  266. X
  267. X    The main difference is that wnewmail checks for mail more often.
  268. X
  269. X    The usage parameters are:
  270. X
  271. X    -i <interval>          how often to check for mail
  272. X                (default: 60 secs if newmail,
  273. X                      10 secs if wnewmail)
  274. X
  275. X    <filename>        name of a folder to monitor
  276. X                (can prefix with '+'/'=', or can
  277. X                 default to the incoming mailbox)
  278. X
  279. X    <filename>=prefix    file to monitor, output with specified
  280. X                prefix when mail arrives.
  281. X
  282. X    If we're monitoring more than one mailbox the program will prefix
  283. X    each line output (if 'newmail') or each cluster of mail (if 'wnewmail')
  284. X    with the basename of the folder the mail has arrived in.  In the 
  285. X    interest of exhaustive functionality, you can also use the "=prefix"
  286. X    suffix (eh?) to specify your own strings to prefix messages with.
  287. X
  288. X    The output format is either:
  289. X
  290. X      newmail:
  291. X         >> New mail from <user> - <subject>
  292. X         >> Priority mail from <user> - <subject>
  293. X
  294. X         >> <folder>: from <user> - <subject>
  295. X         >> <folder>: Priority from <user> - <subject>
  296. X
  297. X      wnewmail:
  298. X         <user> - <subject>
  299. X         Priority: <user> - <subject>
  300. X
  301. X         <folder>: <user> - <subject>
  302. X         <folder>: Priority: <user> - <subject>\fR
  303. X
  304. X**/
  305. X
  306. X#include <stdio.h>
  307. X#include <errno.h>
  308. X#include <sys/types.h>
  309. X#include <sys/stat.h>
  310. X
  311. X#include "defs.h"
  312. X
  313. X#include <signal.h>    /* background jobs ignore some signals... */
  314. X
  315. Xstatic char ident[] = { WHAT_STRING };
  316. X
  317. X#define LINEFEED        (char) 10
  318. X#define BEGINNING        0            /* seek fseek(3S) */
  319. X#define DEFAULT_INTERVAL    60
  320. X
  321. X#define MAX_FOLDERS        25        /* max we can keep track of */
  322. X
  323. X#define NO_SUBJECT    "(No Subject Specified)"
  324. X
  325. X#define metachar(c)    (c == '+' || c == '=' || c == '%')
  326. X
  327. Xchar  *getusername();
  328. Xlong  bytes();
  329. X
  330. Xstruct folder_struct {
  331. X      char        foldername[SLEN];
  332. X      char        prefix[NLEN];
  333. X      FILE         *fd;
  334. X      long        filesize;
  335. X       } folders[MAX_FOLDERS];
  336. X
  337. Xint  interval_time,        /* how long to sleep between checks */
  338. X     debug = 0,            /* include verbose debug output?    */
  339. X     in_window = 0,        /* are we running as 'wnewmail'?    */
  340. X     total_folders = 0,        /* # of folders we're monitoring    */
  341. X     current_folder = 0;    /* struct pointer for looping       */
  342. X
  343. Xchar hostname[SLEN],            /* name of machine we're on         */
  344. X     hostdomain[SLEN];          /* name of domain we're in          */
  345. X
  346. X#ifdef BSD
  347. Xextern int errno;
  348. X#endif
  349. X
  350. Xmain(argc, argv)
  351. Xint argc;
  352. Xchar *argv[];
  353. X{
  354. X    extern char *optarg;
  355. X    extern int   optind, opterr;
  356. X    char *ptr;
  357. X    int c, i, done;
  358. X    long lastsize,
  359. X         newsize;            /* file size for comparison..      */
  360. X
  361. X#ifdef HOSTCOMPILED
  362. X    strncpy(hostname, HOSTNAME, sizeof(hostname));
  363. X#else
  364. X    gethostname(hostname, sizeof(hostname));
  365. X#endif
  366. X    gethostdomain(hostdomain, sizeof(hostdomain));
  367. X
  368. X    interval_time = DEFAULT_INTERVAL;
  369. X    opterr = 0;
  370. X
  371. X    /** let's see if the first character of the basename of the
  372. X        command invoked is a 'w' (e.g. have we been called as
  373. X        'wnewmail' rather than just 'newmail'?)
  374. X    **/
  375. X
  376. X    for (i=0, ptr=(argv[0] + strlen(argv[0])-1); !i && ptr > argv[0]; ptr--)
  377. X      if (*ptr == '/') {
  378. X        in_window = (*(ptr+1) == 'w');
  379. X        i++;
  380. X      }
  381. X
  382. X    if (ptr == argv[0] && i == 0 && argv[0][0] == 'w')
  383. X      in_window = 1;
  384. X
  385. X    while ((c = getopt(argc, argv, "di:w")) != EOF) {
  386. X      switch (c) {
  387. X        case 'd' : debug++;                    break;
  388. X        case 'i' : interval_time = atoi(optarg);        break;
  389. X        case 'w' : in_window = 1;                break;
  390. X        default  : usage();                    exit(1);
  391. X     }
  392. X    }
  393. X
  394. X    if (interval_time < 10)
  395. X      fprintf(stderr,
  396. X"Warning: interval set to %d second%s.  I hope you know what you're doing!\n",
  397. X      interval_time, interval_time == 1 ? "" : "s");
  398. X
  399. X    /* now let's parse the foldernames, if any are given */
  400. X
  401. X    if (optind >= argc) /* get default */
  402. X      add_default_folder();
  403. X    else {
  404. X      while (optind < argc)
  405. X        add_folder(argv[optind++]);
  406. X      pad_prefixes();            /* for nice output...*/
  407. X    }
  408. X
  409. X#ifdef AUTO_BACKGROUND
  410. X    if (! in_window) {
  411. X      if (fork())        /* automatically puts this task in background! */
  412. X        exit(0);
  413. X
  414. X      (void) signal(SIGINT, SIG_IGN);
  415. X      (void) signal(SIGQUIT, SIG_IGN);
  416. X    }
  417. X#endif
  418. X    (void) signal(SIGHUP, SIG_DFL);
  419. X
  420. X    if (in_window && ! debug)
  421. X      printf("Incoming mail:\n");
  422. X
  423. X    while (1) {
  424. X    
  425. X#ifndef AUTO_BACKGROUND        /* won't work if we're nested this deep! */
  426. X      if (getppid() == 1)     /* we've lost our shell! */
  427. X        exit();
  428. X#endif
  429. X      if (! isatty(1))    /* we're not sending output to a tty any more */
  430. X         exit();
  431. X
  432. X      if (debug) printf("\n----\n");
  433. X
  434. X      for (i = 0; i < total_folders; i++) {
  435. X
  436. X        if (debug)
  437. X          printf("[checking folder #%d: %s]\n", i, folders[i].foldername);
  438. X
  439. X        if (folders[i].fd == (FILE *) NULL) {
  440. X
  441. X          if ((folders[i].fd = fopen(folders[i].foldername,"r")) == NULL)
  442. X            if (errno == EACCES) {
  443. X           fprintf(stderr, "\nPermission to monitor %s denied!\n\n",
  444. X             folders[i].foldername);
  445. X               sleep(5);
  446. X               exit(1);
  447. X            }
  448. X        }
  449. X
  450. X        if ((newsize = bytes(folders[i].foldername)) > 
  451. X            folders[i].filesize) {    /* new mail has arrived! */
  452. X
  453. X          if (debug)
  454. X            printf(
  455. X           "\tnew mail has arrived!  old size = %ld, new size=%ld\n",
  456. X           folders[i].filesize, newsize);
  457. X
  458. X          /* skip what we've read already... */
  459. X
  460. X          if (fseek(folders[i].fd, folders[i].filesize, 
  461. X            BEGINNING) != 0)
  462. X            perror("fseek()");
  463. X
  464. X          folders[i].filesize = newsize;
  465. X
  466. X          if (in_window)
  467. X            putchar((char) 007);        /* BEEP!*/
  468. X          else
  469. X            printf("\n\r");    /* blank lines surrounding message */
  470. X
  471. X          read_headers(i);        /* read and display new mail! */
  472. X
  473. X          if (! in_window)
  474. X            printf("\n\r");
  475. X        }
  476. X        else if (newsize != folders[i].filesize) {    /* file SHRUNK! */
  477. X
  478. X          folders[i].filesize = bytes(folders[i].foldername);
  479. X          (void) fclose(folders[i].fd);    /* close it and ...         */
  480. X          folders[i].fd = (FILE *) NULL;    /* let's reopen the file    */
  481. X
  482. X          lastsize = folders[i].filesize;
  483. X          done     = 0;
  484. X
  485. X          while (! done) {
  486. X            sleep(0);    /* basically gives up our CPU slice */
  487. X            newsize = bytes(folders[i].foldername);
  488. X            if (newsize != lastsize)
  489. X              lastsize = newsize;
  490. X        else
  491. X              done++;
  492. X          } 
  493. X            
  494. X          folders[i].filesize = newsize;
  495. X        }
  496. X      }
  497. X
  498. X      sleep(interval_time);
  499. X    }
  500. X}
  501. X
  502. Xint
  503. Xread_headers(current_folder)
  504. Xint current_folder;
  505. X{
  506. X    /** read the headers, output as found given current_folder,
  507. X        the prefix of that folder, and whether we're in a window
  508. X        or not.
  509. X    **/
  510. X
  511. X    char buffer[SLEN], from_whom[SLEN], subject[SLEN];
  512. X    register int subj = 0, in_header = 1, count = 0, priority=0;
  513. X
  514. X    while (fgets(buffer, SLEN, folders[current_folder].fd) != NULL) {
  515. X      if (first_word(buffer,"From ")) {
  516. X        if (real_from(buffer, from_whom)) {
  517. X          subj = 0;
  518. X          priority = 0;
  519. X          in_header = 1;
  520. X          subject[0] ='\0';
  521. X          from_whom[0] ='\0';
  522. X        }
  523. X      }
  524. X      else if (in_header) {
  525. X        if (first_word(buffer,">From")) 
  526. X          forwarded(buffer, from_whom); /* return address */
  527. X        else if (first_word(buffer,"Subject:") ||
  528. X             first_word(buffer,"Re:")) {
  529. X          if (! subj++) {
  530. X            remove_first_word(buffer);
  531. X        strcpy(subject, buffer);
  532. X          }
  533. X        }
  534. X        else if (first_word(buffer,"Priority:")) 
  535. X          priority++;
  536. X        else if (first_word(buffer,"From:")) 
  537. X          parse_arpa_from(buffer, from_whom);
  538. X        else if (buffer[0] == LINEFEED) {
  539. X          in_header = 0;    /* in body of message! */
  540. X          show_header(priority, from_whom, subject, current_folder);
  541. X          count++;
  542. X        }
  543. X      }
  544. X    }
  545. X    return(count);
  546. X}
  547. X
  548. Xadd_folder(name)
  549. Xchar *name;
  550. X{
  551. X    /* add the specified folder to the list of folders...ignore any
  552. X       problems we may having finding it (user could be monitoring
  553. X       a mailbox that doesn't currently exist, for example)
  554. X    */
  555. X
  556. X    char *cp, buf[SLEN];
  557. X
  558. X    if (current_folder > MAX_FOLDERS) {
  559. X      fprintf(stderr,
  560. X              "Sorry, but I can only keep track of %d folders.\n", MAX_FOLDERS);
  561. X      exit(1);
  562. X    }
  563. X
  564. X    /* now let's rip off the suffix "=<string>" if it's there... */
  565. X
  566. X    for (cp = name + strlen(name); cp > name+1 && *cp != '=' ; cp--)
  567. X      /* just keep stepping backwards */ ;
  568. X
  569. X    /* if *cp isn't pointing to the first character we'e got something! */
  570. X
  571. X    if (cp > name+1) {
  572. X
  573. X      *cp++ = '\0';        /* null terminate the filename & get prefix */
  574. X
  575. X      if (metachar(*cp)) cp++;
  576. X
  577. X      strcpy(folders[current_folder].prefix, cp);
  578. X    }
  579. X    else {            /* nope, let's get the basename of the file */
  580. X      for (cp = name + strlen(name); cp > name && *cp != '/'; cp--)
  581. X        /* backing up a bit... */ ;
  582. X
  583. X      if (metachar(*cp)) cp++;
  584. X      if (*cp == '/') cp++;
  585. X
  586. X      strcpy(folders[current_folder].prefix, cp);
  587. X    }
  588. X
  589. X    /* and next let's see what kind of weird prefix chars this user
  590. X       might be testing us with.  We can have '+'|'='|'%' to expand
  591. X       or a file located in the incoming mail dir...
  592. X    */
  593. X
  594. X    if (metachar(name[0]))
  595. X      expand_filename(name, folders[current_folder].foldername);
  596. X    else if (access(name, 00) == -1) {
  597. X      /* let's try it in the mail home directory */
  598. X      sprintf(buf, "%s%s", mailhome, name);
  599. X      if (access(buf, 00) != -1)         /* aha! */
  600. X        strcpy(folders[current_folder].foldername, buf);
  601. X      else
  602. X        strcpy(folders[current_folder].foldername, name);
  603. X    }
  604. X    else
  605. X      strcpy(folders[current_folder].foldername, name);
  606. X
  607. X    /* now let's try to actually open the file descriptor and grab
  608. X       a size... */
  609. X
  610. X    if ((folders[current_folder].fd = 
  611. X          fopen(folders[current_folder].foldername, "r")) == NULL)
  612. X          if (errno == EACCES) {
  613. X        fprintf(stderr, "\nPermission to monitor \"%s\" denied!\n\n",
  614. X             folders[current_folder].foldername);
  615. X        exit(1);
  616. X      }
  617. X
  618. X    folders[current_folder].filesize = 
  619. X          bytes(folders[current_folder].foldername);
  620. X
  621. X    /* and finally let's output what we did */
  622. X
  623. X    if (debug)
  624. X      printf("folder %d: \"%s\" <%s> %s, size = %ld\n",
  625. X          current_folder,
  626. X          folders[current_folder].foldername,
  627. X          folders[current_folder].prefix,
  628. X          folders[current_folder].fd == NULL? "not found" : "opened",
  629. X          folders[current_folder].filesize);
  630. X
  631. X    /* and increment current-folder please! */
  632. X
  633. X    current_folder++;
  634. X    total_folders++;
  635. X}
  636. X
  637. Xadd_default_folder()
  638. X{
  639. X    char    *cp;
  640. X
  641. X    /* this routine will add the users home mailbox as the folder
  642. X     * to monitor.  Since there'll only be one folder we'll never
  643. X     * prefix it either...
  644. X     *    determine mail file from environment variable if found,
  645. X     *    else use password entry
  646. X     */
  647. X    if ((cp = getenv("MAIL")) == NULL)
  648. X      sprintf(folders[0].foldername, "%s%s", mailhome, getusername());
  649. X    else
  650. X      strcpy(folders[0].foldername, cp);
  651. X    
  652. X    folders[0].fd       = fopen(folders[0].foldername, "r");
  653. X    folders[0].filesize = bytes(folders[0].foldername);
  654. X
  655. X    if (debug)
  656. X      printf("default folder: \"%s\" <%s> %s, size = %ld\n",
  657. X          folders[0].foldername,
  658. X          folders[0].prefix,
  659. X          folders[0].fd == NULL? "not found" : "opened",
  660. X          folders[0].filesize);
  661. X
  662. X    total_folders = 1;
  663. X}
  664. X
  665. Xint
  666. Xreal_from(buffer, who)
  667. Xchar *buffer, *who;
  668. X{
  669. X    /***** returns true iff 's' has the seven 'from' fields,
  670. X           initializing the who to the sender *****/
  671. X
  672. X    char junk[SLEN];
  673. X
  674. X    junk[0] = '\0';
  675. X    sscanf(buffer, "%*s %s %*s %*s %*s %*s %s",
  676. X                who, junk);
  677. X    return(junk[0] != '\0');
  678. X}
  679. X
  680. Xforwarded(buffer, who)
  681. Xchar *buffer, *who;
  682. X{
  683. X    /** change 'from' and date fields to reflect the ORIGINATOR of 
  684. X        the message by iteratively parsing the >From fields... **/
  685. X
  686. X    char machine[SLEN], buff[SLEN];
  687. X
  688. X    machine[0] = '\0';
  689. X    sscanf(buffer, "%*s %s %*s %*s %*s %*s %*s %*s %*s %*s %s",
  690. X                who, machine);
  691. X
  692. X    if(machine[0] == '\0')    /* try for address with timezone in date */
  693. X    sscanf(buffer, "%*s %s %*s %*s %*s %*s %*s %*s %*s %s",
  694. X                who, machine);
  695. X
  696. X    if (machine[0] == '\0') /* try for srm address */
  697. X      sscanf(buffer, "%*s %s %*s %*s %*s %*s %*s %*s %s",
  698. X                who, machine);
  699. X
  700. X    if (machine[0] == '\0')
  701. X      sprintf(buff,"anonymous");
  702. X    else
  703. X      sprintf(buff,"%s!%s", machine, who);
  704. X
  705. X    strncpy(who, buff, SLEN);
  706. X}
  707. X
  708. X
  709. Xremove_first_word(string)
  710. Xchar *string;
  711. X{    /** removes first word of string, ie up to first non-white space
  712. X        following a white space! **/
  713. X
  714. X    register int loc;
  715. X
  716. X    for (loc = 0; string[loc] != ' ' && string[loc] != '\0'; loc++) 
  717. X        ;
  718. X
  719. X    while (string[loc] == ' ' || string[loc] == '\t')
  720. X      loc++;
  721. X    
  722. X    move_left(string, loc);
  723. X}
  724. X
  725. Xmove_left(string, chars)
  726. Xchar string[];
  727. Xint  chars;
  728. X{
  729. X    /** moves string chars characters to the left DESTRUCTIVELY **/
  730. X
  731. X    register int i;
  732. X
  733. X    chars--; /* index starting at zero! */
  734. X
  735. X    for (i=chars; string[i] != '\0' && string[i] != '\n'; i++)
  736. X      string[i-chars] = string[i];
  737. X
  738. X    string[i-chars] = '\0';
  739. X}
  740. X
  741. Xshow_header(priority, from, subject, current_folder)
  742. Xint   priority;
  743. Xchar *from, *subject;
  744. Xint   current_folder;
  745. X{
  746. X    /** output header in clean format, including abbreviation
  747. X        of return address if more than one machine name is
  748. X        contained within it! **/
  749. X    char buffer[SLEN];
  750. X    int  loc, i=0, exc=0;
  751. X
  752. X#ifndef INTERNET
  753. X    /* Remove bogus "@host.domain" string. */
  754. X
  755. X    sprintf(buffer, "@%s%s", hostname, hostdomain);
  756. X
  757. X    if (chloc(from, '!') != -1 && in_string(from, buffer))
  758. X      from[strlen(from) - strlen(buffer)] = '\0';
  759. X#endif
  760. X
  761. X    loc = strlen(from);
  762. X
  763. X    while (exc < 2 && loc > 0)
  764. X      if (from[--loc] == '!')
  765. X        exc++;
  766. X
  767. X    if (exc == 2) { /* lots of machine names!  Get last one */
  768. X      loc++;
  769. X      while (loc < strlen(from) && loc < SLEN)
  770. X        buffer[i++] = from[loc++];
  771. X      buffer[i] = '\0';
  772. X      strcpy(from, buffer);
  773. X    }
  774. X
  775. X    if (strlen(subject) < 2)
  776. X      strcpy(subject, NO_SUBJECT);
  777. X    
  778. X    if (in_window)
  779. X      if (total_folders > 1)
  780. X        printf("%s: %s%s -- %s\n",
  781. X           folders[current_folder].prefix,
  782. X           priority? "Priority " : "", from, subject);
  783. X      else
  784. X        printf("%s%s -- %s\n",
  785. X           priority? "Priority " : "", from, subject);
  786. X    else
  787. X      if (total_folders > 1)
  788. X        printf(">> %s: %sail from %s - %s\n\r", 
  789. X          folders[current_folder].prefix,
  790. X          priority? "Priority m" : "M", from, subject);
  791. X      else
  792. X        printf(">> %sail from %s - %s\n\r", 
  793. X          priority? "Priority m" : "M", from, subject);
  794. X}    
  795. X
  796. Xparse_arpa_from(buffer, newfrom)
  797. Xchar *buffer, *newfrom;
  798. X{
  799. X    /** try to parse the 'From:' line given... It can be in one of
  800. X        two formats:
  801. X        From: Dave Taylor <hpcnou!dat>
  802. X        or  From: hpcnou!dat (Dave Taylor)
  803. X        Change 'newfrom' ONLY if sucessfully parsed this entry and
  804. X        the resulting name is non-null! 
  805. X    **/
  806. X
  807. X    char temp_buffer[SLEN], *temp;
  808. X    register int i, j = 0, in_parens;
  809. X
  810. X    temp = (char *) temp_buffer;
  811. X    temp[0] = '\0';
  812. X
  813. X    no_ret(buffer);        /* blow away '\n' char! */
  814. X
  815. X    if (lastch(buffer) == '>') {
  816. X      for (i=strlen("From: "); buffer[i] != '\0' && buffer[i] != '<' &&
  817. X           buffer[i] != '('; i++)
  818. X        temp[j++] = buffer[i];
  819. X      temp[j] = '\0';
  820. X    }
  821. X    else if (lastch(buffer) == ')') {
  822. X      in_parens = 1;
  823. X      for (i=strlen(buffer)-2; buffer[i] != '\0' && buffer[i] != '<'; i--) {
  824. X        switch(buffer[i]) {
  825. X        case ')':    in_parens++;
  826. X            break;
  827. X        case '(':    in_parens--;
  828. X            break;
  829. X        }
  830. X        if(!in_parens) break;
  831. X        temp[j++] = buffer[i];
  832. X      }
  833. X      temp[j] = '\0';
  834. X      reverse(temp);
  835. X    }
  836. X
  837. X    if (strlen(temp) > 0) {        /* mess with buffer... */
  838. X
  839. X      /* remove leading spaces... */
  840. X
  841. X      while (whitespace(temp[0]))
  842. X        temp = (char *) (temp + 1);        /* increment address! */
  843. X
  844. X      /* remove trailing spaces... */
  845. X
  846. X      i = strlen(temp) - 1;
  847. X
  848. X      while (whitespace(temp[i]))
  849. X       temp[i--] = '\0';
  850. X
  851. X      /* if anything is left, let's change 'from' value! */
  852. X
  853. X      if (strlen(temp) > 0)
  854. X        strcpy(newfrom, temp);
  855. X    }
  856. X}
  857. X
  858. Xreverse(string)
  859. Xchar *string;
  860. X{
  861. X    /** reverse string... pretty trivial routine, actually! **/
  862. X
  863. X    char buffer[SLEN];
  864. X    register int i, j = 0;
  865. X
  866. X    for (i = strlen(string)-1; i >= 0; i--)
  867. X      buffer[j++] = string[i];
  868. X
  869. X    buffer[j] = '\0';
  870. X
  871. X    strcpy(string, buffer);
  872. X}
  873. X
  874. Xlong
  875. Xbytes(name)
  876. Xchar *name;
  877. X{
  878. X    /** return the number of bytes in the specified file.  This
  879. X        is to check to see if new mail has arrived....  **/
  880. X
  881. X    int ok = 1;
  882. X    extern int errno;    /* system error number! */
  883. X    struct stat buffer;
  884. X
  885. X    if (stat(name, &buffer) != 0)
  886. X      if (errno != 2) {
  887. X        fprintf(stderr,"Error %d attempting fstat on %s", errno, name);
  888. X        exit(1);
  889. X      }
  890. X      else
  891. X        ok = 0;
  892. X    
  893. X    return(ok ? buffer.st_size : 0);
  894. X}
  895. X
  896. Xchar  *getusername()
  897. X{
  898. X    /** Getting the username on some systems is a real pain, so...
  899. X       This routine is guaranteed to return a usable username **/
  900. X
  901. X    char *return_value, *getlogin(), *cuserid();
  902. X
  903. X    if ((return_value = getlogin()) == NULL)
  904. X      if ((return_value = cuserid(NULL)) == NULL) {
  905. X        printf("Newmail: I can't get username!\n");
  906. X        exit(1);
  907. X      }
  908. X
  909. X    return( (char *) return_value);
  910. X}
  911. X
  912. Xusage()
  913. X{
  914. X    /* print a nice friendly usage message */
  915. X
  916. X    fprintf(stderr, 
  917. X"\nUsage: %s [-d] [-i interval] [-w] {folders}\n");
  918. X    fprintf(stderr, "\nWhere:\n");
  919. X    fprintf(stderr, "  -d\tturns on debugging output\n");
  920. X    fprintf(stderr,
  921. X"  -i D\tsets the interval checking time to 'D' seconds\n");
  922. X    fprintf(stderr,
  923. X"  -w\tforces 'window'-style output, and bypasses auto-background\n\n");
  924. X    fprintf(stderr,
  925. X"folders can be specified by relative or absolute path names, can be the name\n");
  926. X    fprintf(stderr,
  927. X"of a mailbox in the incoming mail directory to check, or can have one of the\n");
  928. X    fprintf(stderr,
  929. X"standard Elm mail directory prefix chars (e.g. '+', '=' or '%').\n");
  930. X    fprintf(stderr,
  931. X"Furthermore, any folder can have '=string' as a suffix to indicate a folder\n");
  932. X    fprintf(stderr,
  933. X"identifier other than the basename of the file\n\n");
  934. X}
  935. X
  936. X
  937. Xexpand_filename(name, store_space)
  938. Xchar *name, *store_space;
  939. X{
  940. X    strcpy(store_space, name);
  941. X    if (expand(store_space) == 0) {
  942. X      fprintf(stderr,"Sorry, but I couldn't expand \"%s\"\n",name);
  943. X      exit(1);
  944. X    }
  945. X}
  946. X
  947. Xpad_prefixes()
  948. X{
  949. X    /** This simple routine is to ensure that we have a nice
  950. X        output format.  What it does is whip through the different
  951. X        prefix strings we've been given, figures out the maximum
  952. X        length, then space pads the other prefixes to match.
  953. X    **/
  954. X
  955. X    register int i, j, len = 0;
  956. X
  957. X    for (i=0; i < total_folders; i++)
  958. X      if (len < (j=strlen(folders[i].prefix)))
  959. X        len = j;
  960. X    
  961. X    for (i=0; i < total_folders; i++)
  962. X      for (j = strlen(folders[i].prefix); j < len; j++)
  963. X        strcat(folders[i].prefix, " ");
  964. X}
  965. SHAR_EOF
  966. chmod 0444 utils/newmail.c || echo "restore of utils/newmail.c fails"
  967. echo "x - extracting utils/printmail (Text)"
  968. sed 's/^X//' << 'SHAR_EOF' > utils/printmail &&
  969. X: Use /bin/sh
  970. X# printmail: part of the Elm mail system
  971. X# @(#)$Id: printmail,v 2.1 89/03/03 17:46:47 syd Exp $
  972. Xif [ "$1" = "-p" ]; then
  973. X  flags="-p";shift
  974. Xfi
  975. Xif [ "$1" != "" ]; then
  976. X  if [ ! -r $1 ]; then
  977. X    echo printmail: cannot open folder $1 1>&2
  978. X    exit 1
  979. X  else
  980. X    flags="$flags -f $1"
  981. X  fi
  982. Xfi
  983. X# and now invoke readmsg
  984. Xexec readmsg $flags \*
  985. SHAR_EOF
  986. chmod 0444 utils/printmail || echo "restore of utils/printmail fails"
  987. echo "x - extracting utils/readmsg.c (Text)"
  988. sed 's/^X//' << 'SHAR_EOF' > utils/readmsg.c &&
  989. X
  990. Xstatic char rcsid[] = "@(#)$Id: readmsg.c,v 2.7 89/03/25 21:47:57 syd Exp $";
  991. X
  992. X/*******************************************************************************
  993. X *  The Elm Mail System  -  $Revision: 2.7 $   $State: Exp $
  994. X *
  995. X *             Copyright (c) 1986, 1987 Dave Taylor
  996. X *             Copyright (c) 1988, 1989 USENET Community Trust
  997. X *******************************************************************************
  998. X * Bug reports, patches, comments, suggestions should be sent to:
  999. X *
  1000. X *    Syd Weinstein, Elm Coordinator
  1001. X *    elm@dsinc.UUCP            dsinc!elm
  1002. X *
  1003. X *******************************************************************************
  1004. X * $Log:    readmsg.c,v $
  1005. X * Revision 2.7  89/03/25  21:47:57  syd
  1006. X * Initial 2.2 Release checkin
  1007. X * 
  1008. X *
  1009. X ******************************************************************************/
  1010. X
  1011. X/** This routine adds the functionality of the "~r" command to the Elm mail 
  1012. X    system while still allowing the user to use the editor of their choice.
  1013. X
  1014. X    The program, without any arguments, tries to read a file in the users home 
  1015. X    directory called ".readmsg" (actually defined in the sysdefs.h system 
  1016. X    defines file) and if it finds it reads the current message.  If it doesn't 
  1017. X    find it, it will return a usage error.
  1018. X
  1019. X    The program can also be called with an explicit message number, list of 
  1020. X    message numbers, or a string to match in the message (including the header).
  1021. X    NOTE that when you use the string matching option it will match the first 
  1022. X    message containing that EXACT (case sensitive) string and then exit.
  1023. X**/
  1024. X
  1025. X#include <stdio.h>
  1026. X#include <ctype.h>
  1027. X
  1028. X#include "defs.h"
  1029. X
  1030. X/** three defines for what level of headers to display **/
  1031. X
  1032. X#define ALL        1
  1033. X#define WEED        2
  1034. X#define NONE        3
  1035. X
  1036. X#define metachar(c)    (c == '=' || c == '+' || c == '%')
  1037. X
  1038. Xstatic char ident[] = { WHAT_STRING };
  1039. X
  1040. X#define  MAX_LIST    25        /* largest single list of arguments */
  1041. X
  1042. X#define  LAST_MESSAGE    9999        /* last message in list ('$' char)  */
  1043. X#define  LAST_CHAR    '$'        /* char to delimit last message..   */
  1044. X#define  STAR        '*'        /* char to delimit all messages...  */
  1045. X
  1046. Xint read_message[MAX_LIST];         /* list of messages to read        */
  1047. Xint messages = 0;            /* index into list of messages      */
  1048. X
  1049. Xint numcmp();                /* strcmp, but for numbers          */
  1050. Xchar *words(),                /* function defined below...        */
  1051. X     *expand_define();            /*     ditto...                     */
  1052. X
  1053. X
  1054. Xextern char *optarg;        /* for parsing the ...             */
  1055. Xextern int   optind;            /*  .. starting arguments           */
  1056. X
  1057. Xchar *getenv();                /* keep lint happy */
  1058. X
  1059. Xmain(argc, argv)
  1060. Xint argc;
  1061. Xchar *argv[];
  1062. X{
  1063. X    FILE *file;                    /* generic file descriptor! */
  1064. X    char filename[SLEN],             /* filename buffer          */
  1065. X         infile[SLEN],            /* input filename        */
  1066. X         buffer[SLEN],             /* file reading buffer      */
  1067. X         string[SLEN],            /* string match buffer      */
  1068. X         *cp;
  1069. X
  1070. X    int current_in_queue = 0,         /* these are used for...     */
  1071. X        current = 0,            /* ...going through msgs     */
  1072. X        list_all_messages = 0,        /* just list 'em all??       */
  1073. X        num,                 /* for argument parsing      */
  1074. X        page_breaks = 0,            /* use "^L" breaks??         */
  1075. X            total,                /* number of msgs current    */
  1076. X        include_headers = WEED,         /* flag: include msg header? */
  1077. X        last_message = 0,             /* flag: read last message?  */
  1078. X        not_in_header = 0,            /* flag: in msg header?      */
  1079. X        string_match = 0;            /* flag: using string match? */
  1080. X
  1081. X    /**** start of the actual program ****/
  1082. X
  1083. X    while ((num = getopt(argc, argv, "nhf:p")) != EOF) {
  1084. X      switch (num) {
  1085. X        case 'n' : include_headers = NONE;        break;
  1086. X        case 'h' : include_headers = ALL;        break;
  1087. X        case 'f' : strcpy(infile, optarg);    
  1088. X               if (metachar(infile[0]))
  1089. X                     if (expand(infile) == 0)
  1090. X                       printf("%s: couldn't expand filename %s!\n", 
  1091. X                      argv[0], infile);
  1092. X               break;
  1093. X        case 'p' : page_breaks++;            break;
  1094. X        case '?' : printf(
  1095. X            "Usage: %s [-n|-h] [-f filename] [-p] <message list>\n",
  1096. X             argv[0]);
  1097. X                 exit(1);
  1098. X      }
  1099. X    }
  1100. X    
  1101. X    /** whip past the starting arguments so that we're pointing
  1102. X        to the right stuff... **/
  1103. X
  1104. X    *argv++;    /* past the program name... */
  1105. X
  1106. X    while (optind-- > 1) {
  1107. X      *argv++;
  1108. X      argc--;
  1109. X    }
  1110. X
  1111. X    /** now let's figure out the parameters to the program... **/
  1112. X
  1113. X    if (argc == 1) {    /* no arguments... called from 'Elm'? */
  1114. X      sprintf(filename, "%s/%s", getenv("HOME"), readmsg_file);
  1115. X      if ((file = fopen(filename, "r")) != NULL) {
  1116. X        fscanf(file, "%d", &(read_message[messages++]));
  1117. X        fclose(file);
  1118. X      }
  1119. X      else {    /* no arguments AND no .readmsg file!! */
  1120. X        fprintf(stderr,
  1121. X            "Usage: readmsg [-n|-h] [-f filename] [-p] <message list>\n");
  1122. X        exit(1);
  1123. X      }
  1124. X    }
  1125. X    else if (! isdigit(*argv[0]) && *argv[0] != LAST_CHAR && 
  1126. X             *argv[0] != STAR) {  
  1127. X      string_match++;
  1128. X     
  1129. X      while (*argv)
  1130. X        sprintf(string, "%s%s%s", string, string[0] == '\0'? "" : " ",
  1131. X            *argv++);
  1132. X    }
  1133. X    else if (*argv[0] == STAR)         /* all messages....   */
  1134. X      list_all_messages++;
  1135. X    else {                       /* list of nums   */
  1136. X
  1137. X      while (--argc > 0) {
  1138. X        num = -1;
  1139. X
  1140. X        sscanf(*argv,"%d", &num);
  1141. X
  1142. X        if (num < 0) {
  1143. X          if (*argv[0] == LAST_CHAR) {
  1144. X            last_message++;
  1145. X        num = LAST_MESSAGE;
  1146. X          }
  1147. X          else {
  1148. X            fprintf(stderr,"I don't understand what '%s' means...\n",
  1149. X            *argv); 
  1150. X               exit(1); 
  1151. X          }
  1152. X        }
  1153. X        else if (num == 0) {    /* another way to say "last" */
  1154. X          last_message++;
  1155. X          num = LAST_MESSAGE;
  1156. X        }
  1157. X
  1158. X        *argv++; 
  1159. X
  1160. X        read_message[messages++] = num;
  1161. X      }
  1162. X
  1163. X      /** and now sort 'em to ensure they're in a reasonable order... **/
  1164. X
  1165. X      qsort(read_message, messages, sizeof(int), numcmp);
  1166. X    }
  1167. X
  1168. X    /** Now let's get to the mail file... **/
  1169. X
  1170. X    if (strlen(infile) == 0) {
  1171. X      if ((cp = getenv("MAIL")) == NULL)
  1172. X        sprintf(infile, "%s/%s", mailhome, getenv("LOGNAME"));
  1173. X      else
  1174. X        strcpy(infile, cp);
  1175. X    }
  1176. X
  1177. X    if ((file = fopen(infile, "r")) == NULL) {
  1178. X      printf("But you have no mail! [ file = %d ]\n", infile);
  1179. X      exit(0);
  1180. X    }
  1181. X
  1182. X    /** Now it's open, let's display some 'ole messages!! **/
  1183. X
  1184. X    if (string_match || last_message) {   /* pass through it once */
  1185. X
  1186. X      if (last_message) {
  1187. X        total = count_messages(file);    /* instantiate count */
  1188. X        for (num=0; num < messages; num++)
  1189. X          if (read_message[num] == LAST_MESSAGE)
  1190. X        read_message[num] = total;
  1191. X      }
  1192. X      else if (string_match)
  1193. X        match_string(file, string);        /* stick msg# in list */
  1194. X
  1195. X      if (total == 0 && ! string_match) {
  1196. X        printf("There aren't any messages to read!\n");
  1197. X        exit(0);
  1198. X      }
  1199. X    }
  1200. X
  1201. X     /** now let's have some fun! **/
  1202. X    
  1203. X    while (fgets(buffer, SLEN, file) != NULL) {
  1204. X      if (real_from(buffer)) {
  1205. X        if (! list_all_messages) {
  1206. X          if (current == read_message[current_in_queue])
  1207. X            current_in_queue++;
  1208. X          if (current_in_queue >= messages) 
  1209. X            exit(0);
  1210. X        }
  1211. X        current++;
  1212. X        not_in_header = 0;    /* we're in the header! */
  1213. X      }
  1214. X      if (current == read_message[current_in_queue] || list_all_messages)
  1215. X        if (include_headers==ALL || not_in_header)
  1216. X          printf("%s", buffer);
  1217. X        else if (strlen(buffer) < 2) {
  1218. X          not_in_header++;
  1219. X          if (include_headers==WEED) 
  1220. X        list_saved_headers(page_breaks);
  1221. X        }
  1222. X        else if (include_headers==WEED)
  1223. X          possibly_save(buffer);     /* check to see if we want this */ 
  1224. X    }
  1225. X    
  1226. X    exit(0);
  1227. X}
  1228. X
  1229. Xint
  1230. Xcount_messages(file)
  1231. XFILE *file;
  1232. X{
  1233. X    /** Returns the number of messages in the file **/
  1234. X
  1235. X    char buffer[SLEN];
  1236. X    int  count = 0;
  1237. X
  1238. X    while (fgets(buffer, SLEN, file) != NULL)
  1239. X      if (strncmp(buffer, "From ", 5) == 0)
  1240. X        count++;
  1241. X
  1242. X    rewind( file );
  1243. X    return( count );
  1244. X}
  1245. X
  1246. Xmatch_string(mailfile, string)
  1247. XFILE *mailfile;
  1248. Xchar *string;
  1249. X{
  1250. X    /** Increment "messages" and put the number of the message
  1251. X        in the message_count[] buffer until we match the specified 
  1252. X        string... **/
  1253. X
  1254. X    char buffer[SLEN];
  1255. X    int  message_count = 0;
  1256. X
  1257. X    while (fgets(buffer, SLEN, mailfile) != NULL) {
  1258. X      if (strncmp(buffer, "From ", 5) == 0)
  1259. X        message_count++;
  1260. X
  1261. X      if (in_string(buffer, string)) {
  1262. X        read_message[messages++] = message_count;
  1263. X        rewind(mailfile);    
  1264. X        return;
  1265. X      }
  1266. X    }
  1267. X
  1268. X    fprintf(stderr,"Couldn't find message containing '%s'\n", string);
  1269. X    exit(1);
  1270. X}
  1271. X
  1272. Xint 
  1273. Xnumcmp(a, b)
  1274. Xint *a, *b;
  1275. X{
  1276. X    /** compare 'a' to 'b' returning less than, equal, or greater
  1277. X        than, accordingly.
  1278. X     **/
  1279. X
  1280. X    return(*a - *b);
  1281. X}
  1282. X
  1283. Xstatic char from[SLEN], subject[SLEN], date[SLEN], to[SLEN];
  1284. X
  1285. Xpossibly_save(buffer)
  1286. Xchar *buffer;
  1287. X{
  1288. X    /** Check to see what "buffer" is...save it if it looks 
  1289. X        interesting... We'll always try to get SOMETHING
  1290. X        by tearing apart the "From " line...  **/
  1291. X
  1292. X    if (strncmp(buffer, "Date:", 5) == 0)
  1293. X      strcpy(date, buffer);
  1294. X    else if (strncmp(buffer, "Subject:", 8) == 0)
  1295. X      strcpy(subject,buffer);
  1296. X    else if (strncmp(buffer,"From:", 5) == 0)
  1297. X      strcpy(from, buffer);
  1298. X    else if (strncmp(buffer,"To: ", 3) == 0)
  1299. X      strncpy(to, buffer, SLEN);
  1300. X    else if (strncmp(buffer,"From ", 5) == 0) {
  1301. X      sprintf(from, "From: %s\n", words(2,1, buffer));    
  1302. X      sprintf(date,"Date: %s",    words(3,7, buffer));
  1303. X      to[0] = '\0';
  1304. X    }
  1305. X}
  1306. X
  1307. Xlist_saved_headers(page_break)
  1308. Xint page_break;
  1309. X{
  1310. X    /** This routine will display the information saved from the
  1311. X        message being listed...If it displays anything it'll end
  1312. X        with a blank line... **/
  1313. X
  1314. X    register int displayed_line = FALSE;
  1315. X    static int messages_listed = 0;
  1316. X
  1317. X    if (messages_listed++) 
  1318. X      if (page_break)
  1319. X        putchar(FORMFEED);    
  1320. X      else
  1321. X        printf(
  1322. X"\n--------------------------------------------------------------------\n\n\n");
  1323. X
  1324. X    if (strlen(from)    > 0) { printf("%s", from);    displayed_line++;}
  1325. X    if (strlen(subject) > 0) { printf("%s", subject); displayed_line++;}
  1326. X    if (strlen(to)      > 0) { printf("%s", to);      displayed_line++;}
  1327. X    if (strlen(date)    > 0) { printf("%s", date);    displayed_line++;}
  1328. X    
  1329. X    if (displayed_line)
  1330. X       putchar('\n');
  1331. X}
  1332. X
  1333. Xchar *words(word, num_words, buffer)
  1334. Xint word, num_words;
  1335. Xchar *buffer;
  1336. X{
  1337. X    /** Return a buffer starting at 'word' and containing 'num_words'
  1338. X        words from buffer.  Assume white space will delimit each word.
  1339. X    **/
  1340. X
  1341. X    static char internal_buffer[SLEN];
  1342. X    char   *wordptr, *bufptr, mybuffer[SLEN], *strtok();
  1343. X    int    wordnumber = 0, copying_words = 0;
  1344. X
  1345. X    internal_buffer[0] = '\0';    /* initialize */
  1346. X
  1347. X    strcpy(mybuffer, buffer);
  1348. X    bufptr = (char *) mybuffer;    /* and setup */
  1349. X
  1350. X    while ((wordptr = strtok(bufptr, " \t")) != NULL) {
  1351. X      if (++wordnumber == word) {
  1352. X        strcpy(internal_buffer, wordptr);
  1353. X        copying_words++;
  1354. X        num_words--;
  1355. X      }
  1356. X      else if (copying_words) {
  1357. X        strcat(internal_buffer, " ");
  1358. X        strcat(internal_buffer, wordptr);
  1359. X        num_words--;
  1360. X      }
  1361. X
  1362. X      if (num_words < 1) 
  1363. X        return((char *) internal_buffer);
  1364. X
  1365. X      bufptr = NULL;
  1366. X    }
  1367. X
  1368. X    return( (char *) internal_buffer);
  1369. X}
  1370. X
  1371. Xint
  1372. Xexpand(infile)
  1373. Xchar *infile;
  1374. X{
  1375. X    /** Expand the filename since the first character is a meta-
  1376. X        character that should expand to the "maildir" variable
  1377. X        in the users ".elmrc" file...
  1378. X
  1379. X        Note: this is a brute force way of getting the entry out 
  1380. X        of the .elmrc file, and isn't recommended for the faint 
  1381. X        of heart!
  1382. X    **/
  1383. X
  1384. X    FILE *rcfile;
  1385. X    char  buffer[SLEN], *expanded_dir, *home, *getenv(), *bufptr;
  1386. X    int   foundit = 0;
  1387. X
  1388. X    bufptr = (char *) buffer;        /* same address */
  1389. X    
  1390. X    if ((home = getenv("HOME")) == NULL) {
  1391. X      printf(
  1392. X         "Can't expand environment variable $HOME to find .elmrc file!\n");
  1393. X      exit(1);
  1394. X    }
  1395. X
  1396. X    sprintf(buffer, "%s/%s", home, elmrcfile);
  1397. X
  1398. X    if ((rcfile = fopen(buffer, "r")) == NULL) {
  1399. X      printf("Can't open your \".elmrc\" file (%s) for reading!\n",
  1400. X         buffer);
  1401. X      exit(1);
  1402. X    }
  1403. X
  1404. X    while (fgets(buffer, SLEN, rcfile) != NULL && ! foundit) {
  1405. X      if (strncmp(buffer, "maildir", 7) == 0 ||
  1406. X          strncmp(buffer, "folders", 7) == 0) {
  1407. X        while (*bufptr != '=' && *bufptr) 
  1408. X          bufptr++;
  1409. X        bufptr++;            /* skip the equals sign */
  1410. X        while (whitespace(*bufptr) && *bufptr)
  1411. X          bufptr++; 
  1412. X        home = bufptr;        /* remember this address */
  1413. X
  1414. X        while (! whitespace(*bufptr) && *bufptr != '\n')
  1415. X          bufptr++;
  1416. X
  1417. X        *bufptr = '\0';        /* remove trailing space */
  1418. X         foundit++;
  1419. X      }
  1420. X    }
  1421. X
  1422. X    fclose(rcfile);            /* be nice... */
  1423. X
  1424. X    if (! foundit) {
  1425. X      printf("Couldn't find \"maildir\" in your .elmrc file!\n");
  1426. X      exit(1);
  1427. X    }
  1428. X
  1429. X    /** Home now points to the string containing your maildir, with
  1430. X        no leading or trailing white space...
  1431. X    **/
  1432. X
  1433. X    expanded_dir = expand_define(home);
  1434. X
  1435. X    sprintf(buffer, "%s%s%s", expanded_dir, 
  1436. X        (expanded_dir[strlen(expanded_dir)-1] == '/' ||
  1437. X        infile[0] == '/') ? "" : "/", (char *) infile+1);
  1438. X
  1439. X    strcpy(infile, buffer);
  1440. X}
  1441. X
  1442. Xchar *expand_define(maildir)
  1443. Xchar *maildir;
  1444. X{
  1445. X    /** This routine expands any occurances of "~" or "$var" in
  1446. X        the users definition of their maildir directory out of
  1447. X        their .elmrc file.
  1448. X
  1449. X        Again, another routine not for the weak of heart or staunch
  1450. X        of will!
  1451. X    **/
  1452. X
  1453. X    static char buffer[SLEN];    /* static buffer AIEE!! */
  1454. X    char   name[SLEN],        /* dynamic buffer!! (?) */
  1455. X           *nameptr,           /*  pointer to name??     */
  1456. X           *value;              /* char pointer for munging */
  1457. X
  1458. X    if (*maildir == '~') 
  1459. X      sprintf(buffer, "%s%s", getenv("HOME"), ++maildir);
  1460. X    else if (*maildir == '$') {     /* shell variable */
  1461. X
  1462. X      /** break it into a single word - the variable name **/
  1463. X
  1464. X      strcpy(name, (char *) maildir + 1);    /* hurl the '$' */
  1465. X      nameptr = (char *) name;
  1466. X      while (*nameptr != '/' && *nameptr) nameptr++;
  1467. X      *nameptr = '\0';    /* null terminate */
  1468. X      
  1469. X      /** got word "name" for expansion **/
  1470. X
  1471. X      if ((value = getenv(name)) == NULL) {
  1472. X        printf("Couldn't expand shell variable $%s in .elmrc!\n", name);
  1473. X        exit(1);
  1474. X      }
  1475. X      sprintf(buffer, "%s%s", value, maildir + strlen(name) + 1);
  1476. X    }
  1477. X    else
  1478. X       strcpy(buffer, maildir);
  1479. X
  1480. X    return( ( char *) buffer);
  1481. X}
  1482. X
  1483. Xint
  1484. Xreal_from(buffer)
  1485. Xchar *buffer;
  1486. X{
  1487. X    /***** Returns true iff 's' has the seven 'from' fields, (or
  1488. X           8 - some machines include the TIME ZONE!!!) *****/
  1489. X
  1490. X    char sixthword[STRING], seventhword[STRING],
  1491. X         eighthword[STRING], ninthword[STRING];
  1492. X
  1493. X    /* From <user> <day> <month> <day> <hr:min:sec> <year> */
  1494. X
  1495. X    if(strncmp(buffer, "From ", 5) != 0)
  1496. X      return(FALSE);
  1497. X
  1498. X    /* Extract 6th, 7th, 8th, and 9th words */
  1499. X    seventhword[0] = eighthword[0] = ninthword[0] = '\0';
  1500. X    sscanf(buffer, "%*s %*s %*s %*s %*s %s %s %s %s",
  1501. X      sixthword, seventhword, eighthword, ninthword);
  1502. X
  1503. X    /* Not a from line if 6th word doesn't have colons for time field */
  1504. X    if(strlen(sixthword) < 3)
  1505. X      return(FALSE);
  1506. X    if (sixthword[1] != ':' && sixthword[2] != ':')
  1507. X      return(FALSE);        
  1508. X
  1509. X    /* Not a from line if there is no seventh word */
  1510. X    if(seventhword[0] == '\0')
  1511. X      return(FALSE);
  1512. X
  1513. X    /* Not a from line if there is a ninthword */
  1514. X    if (eighthword[0] != '\0') {
  1515. X      if(ninthword[0] != '\0')
  1516. X        return(FALSE);    
  1517. X    }
  1518. X
  1519. X    return(TRUE);
  1520. X}
  1521. SHAR_EOF
  1522. chmod 0444 utils/readmsg.c || echo "restore of utils/readmsg.c fails"
  1523. rm -f s2_seq_.tmp
  1524. echo "You have unpacked the last part"
  1525. exit 0
  1526.  
  1527.